import { Inject, Provide } from '@midwayjs/core';
import { Context } from '@midwayjs/koa';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { In, Repository } from 'typeorm';
import {
  CreateTeacherDto,
  UpdateTeacherDto,
  QueryTeacherDto,
} from '@dto/teacher.dto';
import { TeacherEntity } from '@entity/teacher.entity';
import { resBuild } from '../utils/resBuild';
import { getOperator, isEmpty } from '../utils';
import { User } from '@entity/framework/system/SysUser';
import { genHashPsw } from '@utils/password';
import { SysUserRole } from '@entity/framework/system/SysUserRole';
import { SysUserPost } from '@entity/framework/system/SysUserPost';
import { SysDept } from '@entity/framework/system/SysDept';

@Provide()
export class TeacherDao {
  @Inject()
  ctx: Context;
  @InjectEntityModel(TeacherEntity)
  teacherEntityRep: Repository<TeacherEntity>;
  @InjectEntityModel(User)
  userRepo: Repository<User>;

  async create(createTeacherDto: CreateTeacherDto) {
    await this.teacherEntityRep.manager.transaction(async manager => {
      const userRepo = manager.getRepository(User);
      const teacherRepo = manager.getRepository(TeacherEntity);
      const userRoleRepo = manager.getRepository(SysUserRole);

      const teachId = createTeacherDto.teachId;
      if (!teachId) {
        throw new Error('教师工号(teachId)不能为空');
      }
      // 工号即登录账号，查重
      const existUser = await userRepo.findOne({
        where: { userName: teachId },
      });
      if (existUser) {
        throw new Error(`登录账号(工号)已存在: ${teachId}`);
      }

      // 创建系统用户，账号默认使用 teachId；兼容非前缀字段
      const newUser = userRepo.create({
        userName: createTeacherDto.userName || teachId,
        nickName:
          createTeacherDto.userNickName ??
          createTeacherDto.nickName ??
          teachId,
        password: genHashPsw(
          teachId +
          '123456'
        ),
        email: (createTeacherDto.userEmail ?? createTeacherDto.email) || '',
        phonenumber:
          createTeacherDto.userPhonenumber ?? createTeacherDto.phonenumber ?? '',
        sex: isEmpty(createTeacherDto.userSex)
          ? isEmpty(createTeacherDto.sex)
            ? undefined
            : createTeacherDto.sex
          : createTeacherDto.userSex,
        deptId: isEmpty(createTeacherDto.userDeptId)
          ? isEmpty(createTeacherDto.deptId)
            ? undefined
            : createTeacherDto.deptId
          : createTeacherDto.userDeptId,
        status: createTeacherDto.userStatus ?? createTeacherDto.status ?? '0',
        remark: createTeacherDto.remark,
      } as Partial<User>);
      newUser.setCreateBy(getOperator(this.ctx));
      const savedUser = await userRepo.save(newUser);
      const list = [{ userId: savedUser.userId, roleId: 4 }];
      await userRoleRepo.save(list);
      // 创建教师并绑定 userId
      const entity = teacherRepo.create({
        ...createTeacherDto,
        userId: savedUser.userId,
        delFlag: '0',
      });
      entity.setCreateBy(getOperator(this.ctx));
      entity.setUpdateBy(getOperator(this.ctx));
      await teacherRepo.save(entity);
    });
    return resBuild.success();
  }

  async list(query: QueryTeacherDto) {
    const qb = this.teacherEntityRep
      .createQueryBuilder('entity')
      .leftJoinAndSelect('entity.user', 'user')
      .leftJoinAndSelect('user.dept', 'dept')

    if (!isEmpty(query.userId)) {
      qb.andWhere('entity.userId = :userId', { userId: query.userId });
    }
    if (!isEmpty(query.email)) {
      qb.andWhere('entity.email = :email', { email: query.email });
    }
    if (!isEmpty(query.nickName)) {
      qb.andWhere('user.nickName ILIKE :nickName', {
        nickName: `%${query.nickName}%`,
      });
    }
    if (!isEmpty(query.teachId)) {
      qb.andWhere('entity.teachId ILIKE :teachId', {
        teachId: `%${query.teachId}%`,
      });
    }

    if (!isEmpty(query.majorField)) {
      qb.andWhere('entity.majorField ILIKE :majorField', {
        majorField: `%${query.majorField}%`,
      });
    }
    if (!isEmpty(query.status)) {
      qb.andWhere('entity.status = :status', { status: query.status });
    }
    if (!isEmpty(query.deptId)) {
      qb.andWhere('dept.deptId = :deptId', { deptId: query.deptId });
    }

    if (query.pageNum && query.pageSize) {
      qb.skip(query.pageSize * (query.pageNum - 1)).take(query.pageSize);
    }
    qb.addOrderBy('entity.createTime', 'DESC');
    const [rows, total] = await qb.getManyAndCount();
    return resBuild.list(rows, total);
  }

  /**
   * 根据学院ID获取教师列表（不分页）
   */
  async listByDept(deptId: number) {
    const teachers = await this.teacherEntityRep
      .createQueryBuilder('entity')
      .leftJoinAndSelect('entity.user', 'user')
      .leftJoinAndSelect('user.dept', 'dept')
      .where('dept.deptId = :deptId', { deptId })
      .andWhere('entity.delFlag = :delFlag', { delFlag: '0' })
      .andWhere('entity.status = :status', { status: '0' })
      .orderBy('entity.createTime', 'DESC')
      .getMany();

    return resBuild.data(teachers);
  }

  async detail(teacherId: number) {
    const qb = this.teacherEntityRep
      .createQueryBuilder('entity')
      .leftJoin(User, 'usr', 'usr.userId = entity.userId')
      .leftJoin(SysDept, 'dept', 'dept.deptId = usr.deptId')
      .where('entity.teacherId = :teacherId', { teacherId })
      .andWhere('entity.delFlag = :delFlag', { delFlag: '0' });

    // 教师字段
    qb.addSelect('entity.teacherId', 'teacherId');
    qb.addSelect('entity.userId', 'userId');
    qb.addSelect('entity.teachId', 'teachId');
    qb.addSelect('entity.email', 'email');
    qb.addSelect('entity.summary', 'summary');
    qb.addSelect('entity.majorField', 'majorField');
    qb.addSelect('entity.remark', 'remark');
    qb.addSelect('entity.status', 'status');

    // 用户字段
    qb.addSelect('usr.userName', 'userName');
    qb.addSelect('usr.nickName', 'nickName');
    qb.addSelect('usr.deptId', 'deptId');
    qb.addSelect('usr.email', 'userEmail');
    qb.addSelect('usr.phonenumber', 'phonenumber');
    qb.addSelect('usr.sex', 'sex');
    qb.addSelect('usr.status', 'userStatus');

    // 部门字段
    qb.addSelect('dept.deptName', 'deptName');

    const row = await qb.getRawOne();
    return resBuild.data(row);
  }

  async update(updateTeacherDto: UpdateTeacherDto) {
    await this.teacherEntityRep.manager.transaction(async manager => {
      const teacherRepo = manager.getRepository(TeacherEntity);
      const userRepo = manager.getRepository(User);
      const userRoleRepo = manager.getRepository(SysUserRole);
      const userPostRepo = manager.getRepository(SysUserPost);

      const { teacherId } = updateTeacherDto;
      const existTeacher = await teacherRepo.findOneBy({ teacherId });
      if (!existTeacher) {
        throw new Error('教师记录不存在');
      }

      const body: any = updateTeacherDto as any;

      const userId: number | undefined = body.userId ?? existTeacher.userId;
      if (userId) {
        const userPatch: any = { userId };
        if (
          typeof body.userNickName !== 'undefined' ||
          typeof body.nickName !== 'undefined'
        )
          userPatch.nickName = body.userNickName ?? body.nickName;
        if (
          typeof body.userEmail !== 'undefined' ||
          typeof body.email !== 'undefined'
        )
          userPatch.email = body.userEmail ?? body.email;
        if (
          typeof body.userPhonenumber !== 'undefined' ||
          typeof body.phonenumber !== 'undefined'
        )
          userPatch.phonenumber = body.userPhonenumber ?? body.phonenumber;
        if (
          typeof body.userSex !== 'undefined' ||
          typeof body.sex !== 'undefined'
        )
          userPatch.sex = body.userSex ?? body.sex;
        if (
          typeof body.userDeptId !== 'undefined' ||
          typeof body.deptId !== 'undefined'
        )
          userPatch.deptId = body.userDeptId ?? body.deptId;
        if (
          typeof body.userStatus !== 'undefined' ||
          typeof body.status !== 'undefined'
        )
          userPatch.status = body.userStatus ?? body.status;
        if (typeof body.remark !== 'undefined') userPatch.remark = body.remark;
        const rawPwd = body.userPassword ?? body.password;
        if (typeof rawPwd !== 'undefined' && rawPwd) {
          userPatch.password = await genHashPsw(rawPwd);
        }

        const keys = Object.keys(userPatch).filter(k => k !== 'userId');
        if (keys.length > 0) {
          const tempUser = userRepo.create(userPatch as Partial<User>);
          tempUser.setUpdateBy(getOperator(this.ctx));
          await userRepo.save(tempUser);
        }

        const roleIds = Array.isArray(body.userRoleIds)
          ? body.userRoleIds
          : Array.isArray(body.roleIds)
            ? body.roleIds
            : undefined;
        if (roleIds) {
          await userRoleRepo.delete({ userId });
          if (roleIds.length > 0) {
            const list = roleIds.map((roleId: number) => ({ userId, roleId }));
            await userRoleRepo.save(list);
          }
        }

        const postIds = Array.isArray(body.userPostIds)
          ? body.userPostIds
          : Array.isArray(body.postIds)
            ? body.postIds
            : undefined;
        if (postIds) {
          await userPostRepo.delete({ userId });
          if (postIds.length > 0) {
            const list = postIds.map((postId: number) => ({ userId, postId }));
            await userPostRepo.save(list);
          }
        }
      }

      // 更新教师信息（仅更新提供的字段）
      const teacherPatch: Partial<TeacherEntity> = { teacherId };
      if (typeof body.userId !== 'undefined') teacherPatch.userId = body.userId;
      if (typeof body.teachId !== 'undefined') teacherPatch.teachId = body.teachId;
      if (typeof body.email !== 'undefined') teacherPatch.email = body.email;
      if (typeof body.summary !== 'undefined') teacherPatch.summary = body.summary;
      if (typeof body.majorField !== 'undefined') teacherPatch.majorField = body.majorField;
      if (typeof body.remark !== 'undefined') teacherPatch.remark = body.remark;
      if (typeof body.status !== 'undefined') teacherPatch.status = body.status;

      const entity = teacherRepo.create(teacherPatch);
      entity.setUpdateBy(getOperator(this.ctx));
      await teacherRepo.save(entity);
    });

    return resBuild.success();
  }

  async remove(teacherIds: Array<number>) {
    await this.teacherEntityRep.manager.transaction(async manager => {
      const teacherRepo = manager.getRepository(TeacherEntity);
      const userRepo = manager.getRepository(User);
      const userRoleRepo = manager.getRepository(SysUserRole);

      // 先拿到关联的 userId 列表
      const rows = await teacherRepo.find({
        where: { teacherId: In(teacherIds) },
        select: ['userId'],
      });
      const userIds = rows.map(r => r.userId).filter(id => typeof id === 'number');

      // 删除教师
      await teacherRepo.delete({ teacherId: In(teacherIds) });

      // 删除用户关联和用户本身
      if (userIds.length > 0) {
        await userRoleRepo.delete({ userId: In(userIds) });
        await userRepo.delete({ userId: In(userIds) });
      }
    });

    return resBuild.success();
  }

  /**
   * 批量创建或更新教师（用于导入）
   */
  async batchImport(teachers: any[], updateSupport: boolean) {
    const results = {
      successCount: 0,
      failCount: 0,
      failMessages: [] as string[],
    };

    await this.teacherEntityRep.manager.transaction(async manager => {
      const userRepo = manager.getRepository(User);
      const teacherRepo = manager.getRepository(TeacherEntity);
      const userRoleRepo = manager.getRepository(SysUserRole);

      for (const teacherData of teachers) {
        try {
          // 查找是否已存在（按工号）
          const existingTeacher = await teacherRepo
            .createQueryBuilder('teacher')
            .leftJoin(User, 'usr', 'usr.userId = teacher.userId')
            .where('teacher.teachId = :teachId', { teachId: teacherData.teachId })
            .andWhere('teacher.delFlag = :delFlag', { delFlag: '0' })
            .select(['teacher.teacherId', 'teacher.userId', 'usr.userId'])
            .getRawOne();

          if (existingTeacher && !updateSupport) {
            // 存在且不支持更新，跳过
            results.failMessages.push(`工号${teacherData.teachId}已存在，跳过导入`);
            results.failCount++;
            continue;
          }

          if (existingTeacher && updateSupport) {
            // 更新逻辑
            const userId = existingTeacher.teacher_userId;
            const teacherId = existingTeacher.teacher_teacherId;

            // 更新用户表
            await userRepo.update(
              { userId },
              {
                nickName: teacherData.nickName,
                email: teacherData.email || '',
                phonenumber: teacherData.phonenumber || '',
                deptId: teacherData.deptId,
                updateBy: getOperator(this.ctx),
                updateTime: new Date(),
              }
            );

            // 更新教师表
            await teacherRepo.update(
              { teacherId },
              {
                email: teacherData.email || '',
                summary: teacherData.summary || '',
                majorField: teacherData.majorField || '',
                updateBy: getOperator(this.ctx),
                updateTime: new Date(),
              }
            );

            // 确保用户有教师角色（roleId = 4）
            const existingRole = await userRoleRepo.findOne({
              where: { userId, roleId: 4 },
            });
            if (!existingRole) {
              await userRoleRepo.save({ userId, roleId: 4 });
            }

            results.successCount++;
          } else {
            // 新增逻辑
            const teachId = teacherData.teachId;

            // 创建用户（密码：工号+123456）
            const newUser = userRepo.create({
              userName: teachId,
              nickName: teacherData.nickName,
              password: genHashPsw(teachId + '123456'),
              email: teacherData.email || '',
              phonenumber: teacherData.phonenumber || '',
              deptId: teacherData.deptId,
            });
            newUser.setCreateBy(getOperator(this.ctx));
            const savedUser = await userRepo.save(newUser);

            // 绑定教师角色（roleId = 4）
            await userRoleRepo.save({
              userId: savedUser.userId,
              roleId: 4,
            });

            // 创建教师
            const teacher = teacherRepo.create({
              userId: savedUser.userId,
              teachId: teacherData.teachId,
              email: teacherData.email,
              summary: teacherData.summary,
              majorField: teacherData.majorField,
              status: teacherData.status || '0',
              delFlag: '0',
            } as Partial<TeacherEntity>);
            teacher.setCreateBy(getOperator(this.ctx));
            teacher.setUpdateBy(getOperator(this.ctx));
            await teacherRepo.save(teacher);

            results.successCount++;
          }
        } catch (error) {
          results.failCount++;
          results.failMessages.push(
            `工号${teacherData.teachId}导入失败：${error.message}`
          );
        }
      }
    });

    return results;
  }
}
